package com.me.study.javaBasic.dataType;

import com.me.common.util.SleepUtil;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * （线程不安全！！！）DecimalFormat 测试：BigDecimal 格式化   <p>
 *  见  https://mp.weixin.qq.com/s/ENKwVqPE1cuOgE51ODJnnw
 *
 * @author ME
 * @date 2021/4/26
 */
public class TestBigDecimalFormat {

    private double myNum;

    /**
     * 千分位输出，并保留 n位小数只能用这种配置 `,##0.00`  <p>
     *     `#.00` 格式化 0.9 的时候会输出 `.90`
     */
    @Test
    public void moneyFormat() {
        Assert.assertEquals("保留n位小数只能用这种配置 `0.00`",
                "0.00", new DecimalFormat("0.00").format(new BigDecimal("0")));
        Assert.assertEquals("不能用这种配置 `#.00`",
                ".00", new DecimalFormat("#.00").format(new BigDecimal("0")));

        Assert.assertEquals("保留n位小数只能用这种配置 `#0.00`",
                "1230.00", new DecimalFormat("#0.00").format(new BigDecimal("1230")));
        Assert.assertEquals("保留n位小数不能用这种配置！！！ `##.00`",
                ".95", new DecimalFormat("##.00").format(new BigDecimal("0.9456")));
        Assert.assertEquals("逗号千分位 `#,##0.00`",
                "1,230,000.00", new DecimalFormat(",##0.00").format(new BigDecimal("1230000")));
        Assert.assertEquals("本地化千分位 `,##0.00`",
                "1,230,000.00", new DecimalFormat(",##0.00").format(new BigDecimal("1230000")));
        Assert.assertEquals("千分位不能用这种配置！！！ `##0.00`",
                "1230.00", new DecimalFormat("##0.00").format(new BigDecimal("1230")));
    }

    /**
     * 00.00   位数不足补0；超过的话，整数部分不处理，小数部分截取（五舍六入）
     */
    @Test
    public void format1() {
        DecimalFormat format1 = new DecimalFormat("000.000");

        Assert.assertEquals("模版符号为 `0`，无论整数部分、小数部分位数不足补 `0`",
                "005.900", format1.format(new BigDecimal("5.9")));
        Assert.assertEquals("模版符号为 `0`，表示不足位数补 `0`",
                "025.900", format1.format(new BigDecimal("25.90")));
        Assert.assertEquals("超过的话，整数部分不处理，小数部分截取（五舍六入）",
                "4125.004", format1.format(new BigDecimal("4125.0045")));
        Assert.assertEquals("超过的话，整数部分不处理，小数部分截取（五舍六入）",
                "4125.005", format1.format(new BigDecimal("4125.0046")));
        Assert.assertEquals("超过的话，整数部分不处理，小数部分截取（五舍六入）",
                "4126.000", format1.format(new BigDecimal("4125.9999")));

        // 设置为四舍五入
        format1.setRoundingMode(RoundingMode.HALF_UP);
    }

    /**
     * #.##    位数不足不处理；超过的话，整数部分不处理，小数部分截取（五舍六入）    <p>
     * 会自动去掉小数位的 0
     */
    @Test
    public void format2() {
        DecimalFormat format1 = new DecimalFormat("##.###");

        Assert.assertEquals("模版符号为 `#`，自动去掉无意义的 0",
                "0.9", format1.format(new BigDecimal("000.90")));
        Assert.assertEquals("模版符号为 `#`，无论整数部分、小数部分位数不足不处理",
                "5.9", format1.format(new BigDecimal("5.9")));
        Assert.assertEquals("模版符号为 `#`，无论整数部分、小数部分位数不足不处理",
                "25.9", format1.format(new BigDecimal("25.90")));
        Assert.assertEquals("超过的话，整数部分不处理，小数部分截取（五舍六入）",
                "4125.004", format1.format(new BigDecimal("4125.0045")));
        Assert.assertEquals("超过的话，整数部分不处理，小数部分截取（五舍六入）",
                "4125.005", format1.format(new BigDecimal("4125.0046")));
        Assert.assertEquals("超过的话，整数部分不处理，小数部分截取（五舍六入）",
                "4126", format1.format(new BigDecimal("4125.9999")));
    }

    /**
     * %、‰    把数字转换为 百分数、千分数
     */
    @Test
    public void format3() {
        DecimalFormat format1 = new DecimalFormat("##0.00%");
        DecimalFormat format2 = new DecimalFormat("###.##%");
        DecimalFormat format3 = new DecimalFormat("0.00‰");
        DecimalFormat format4 = new DecimalFormat("#.##‰");

        Assert.assertEquals("%、‰    把数字转换为 百分数、千分数",
                "4.10%", format1.format(0.041));
        Assert.assertEquals("%、‰    把数字转换为 百分数、千分数",
                "4.1%", format2.format(0.041));
        Assert.assertEquals("%、‰    把数字转换为 百分数、千分数",
                "2040.00‰", format3.format(2.04));
        Assert.assertEquals("%、‰    把数字转换为 百分数、千分数",
                "2040‰", format4.format(2.04));
    }

    /**
     * `,`    分组分隔符，百分位、千分位
     */
    @Test
    public void format4() {
        Assert.assertEquals("`,`    分组分隔符：千分位",
                "1,220", new DecimalFormat(",###").format(myNum));
        Assert.assertEquals("`,`    分组分隔符：百分位",
                "12,20", new DecimalFormat(",##").format(myNum));
        Assert.assertEquals("`,`    分组分隔符",
                "3,456,789.2", new DecimalFormat(",###.##").format(3456789.2));
        Assert.assertEquals("`,`    分组分隔符",
                "3,456,789.20", new DecimalFormat(",###.00").format(3456789.2));

        Assert.assertEquals("分隔符 `,` 左边是无效的",
                "12,20", new DecimalFormat("###,##").format(myNum));
    }

    /**
     * `¤`    本地货币符号
     */
    @Test
    public void format5() {
        Assert.assertEquals("%、‰    把数字转换为 百分数、千分数",
                "1,220.05￥", new DecimalFormat(",000.00¤").format(myNum));
        Assert.assertEquals("%、‰    把数字转换为 百分数、千分数",
                "1,220.05￥", new DecimalFormat(",000.¤00").format(myNum));
        Assert.assertEquals("%、‰    把数字转换为 百分数、千分数",
                "￥1,220.05", new DecimalFormat("¤,000.00").format(myNum));
        Assert.assertEquals("%、‰    把数字转换为 百分数、千分数",
                "￥1,220.05￥", new DecimalFormat("¤,000.¤00").format(myNum));

        Assert.assertEquals("世界货币表达形式：`¤¤` ",
                "1,220.05CNY", new DecimalFormat(",000.00¤¤").format(myNum));
    }

    @Test
    public void notThreadSafe() {
        DecimalFormat format = new DecimalFormat(",###.00");
        List<BigDecimal> lists = new ArrayList<BigDecimal>() {
            {
                add(new BigDecimal("542.156"));
                add(new BigDecimal("1.68"));
                add(new BigDecimal("984.12"));
                add(new BigDecimal("50.196"));
                add(new BigDecimal("3671.045"));
                add(new BigDecimal("3.16"));
                add(new BigDecimal("10.11"));
                add(new BigDecimal("2.17"));
                add(new BigDecimal("8.16"));
                add(new BigDecimal("31.45"));
            }
        };
        ExecutorService executorService = Executors.newCachedThreadPool();
        CountDownLatch countDownLatch = new CountDownLatch(lists.size());
        for (BigDecimal list : lists) {
            executorService.submit(() -> {
                try {
                    countDownLatch.await();
                    System.out.println(format.format(list));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
            countDownLatch.countDown();
        }
        SleepUtil.seconds(2);
    }

    @Before
    public void before() {
        myNum = 1220.0455;
    }

}
